package com.mini.cn.goods.io.netty.ws;

import com.mini.cn.goods.io.netty.io.Session;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Created with IntelliJ IDEA.
 * User: fly
 * Date: 2020-01-16
 * Time: 7:28 下午
 */
public final class WebSocketSession extends Session {

    public static final String USERKEY = "USERKEY";

    protected final List<byte[]> bytes;

    public WebSocketSession(Channel channel) {
        super(channel);
        bytes = new ArrayList<byte[]>();
    }

    public List<byte[]> getBytes() {
        return bytes;
    }

    public ChannelFuture sendText(String message) {

        return channel.writeAndFlush(new TextWebSocketFrame(message));
    }

    public ChannelFuture sendText(ByteBuf byteBuf) {
        return channel.writeAndFlush(new TextWebSocketFrame(byteBuf));
    }

    public ChannelFuture sendText(ByteBuffer byteBuffer) {
        ByteBuf buffer = channel.alloc().buffer(byteBuffer.remaining());
        buffer.writeBytes(byteBuffer);
        return channel.writeAndFlush(new TextWebSocketFrame(buffer));
    }

    public ChannelFuture sendText(TextWebSocketFrame textWebSocketFrame) {
        return channel.writeAndFlush(textWebSocketFrame);
    }

    public ChannelFuture sendBinary(byte[] bytes) {
        ByteBuf buffer = channel.alloc().buffer(bytes.length);
        return channel.writeAndFlush(new BinaryWebSocketFrame(buffer.writeBytes(bytes)));
    }

    public ChannelFuture sendBinary(ByteBuf byteBuf) {
        return channel.writeAndFlush(new BinaryWebSocketFrame(byteBuf));
    }

    //发送拆包的api
    public ChannelFuture sendUnpackBinary(List<byte[]> bytes) {
        //有多个包
        if (bytes == null || bytes.isEmpty()) {
            throw new IllegalStateException("send package can not empty....");
        }
        int index = 0;
        int size = bytes.size();
        for (byte[] bs : bytes) {
            //有多个包
            ByteBuf buffer = channel.alloc().buffer(bs.length);
            if (index == 0) {
                //第一个包
                if (size == 1) {
                    return channel.writeAndFlush(new BinaryWebSocketFrame(buffer.writeBytes(bs)));
                } else {
                    channel.writeAndFlush(new BinaryWebSocketFrame(false, 0, buffer.writeBytes(bs)));
                }
            } else {
                if (index == size - 1) {
                    //最后一个包
                    return channel.writeAndFlush(new ContinuationWebSocketFrame(true, 0, buffer.writeBytes(bs)));
                } else {
                    //中间的拆包
                    channel.writeAndFlush(new ContinuationWebSocketFrame(false, 0, buffer.writeBytes(bs)));
                }
            }
            index++;
        }
        return null;
    }


    /***
     * //发送拆包的api 用统一的ByteBuf
     * @param byteBufs byteBuf队列
     * @param isRelease 是否释放内存 release
     * @return
     */
    public ChannelFuture sendUnpackBinaryByByteBufs(List<ByteBuf> byteBufs, boolean isRelease) {
        if (byteBufs == null || byteBufs.isEmpty()) {
            throw new IllegalStateException("send package can not empty....");
        }
        //有多个包
        int index = 0;
        int size = byteBufs.size();
        for (ByteBuf bs : byteBufs) {
            if (!isRelease) {
                //计数器加一 防止release
                bs = bs.duplicate().retain();
            }
            if (index == 0) {
                //第一个包
                if (size == 1) {
                    return channel.writeAndFlush(new BinaryWebSocketFrame(bs));
                } else {
                    channel.writeAndFlush(new BinaryWebSocketFrame(false, 0, bs));
                }
            } else {
                if (index == size - 1) {
                    //最后一个包
                    return channel.writeAndFlush(new ContinuationWebSocketFrame(true, 0, bs));
                } else {
                    //中间的拆包
                    channel.writeAndFlush(new ContinuationWebSocketFrame(false, 0, bs));
                }
            }
            index++;
        }
        return null;
    }

    public ChannelFuture sendBinary(ByteBuffer byteBuffer) {
        ByteBuf buffer = channel.alloc().buffer(byteBuffer.remaining());
        buffer.writeBytes(byteBuffer);
        return channel.writeAndFlush(new BinaryWebSocketFrame(buffer));
    }

    public ChannelFuture sendBinary(BinaryWebSocketFrame binaryWebSocketFrame) {
        return channel.writeAndFlush(binaryWebSocketFrame);
    }

    @Override
    public int hashCode() {
        Object o = this.getAttribute(USERKEY);
        if (o != null) {
            return Objects.hashCode(o.toString());
        }
        return 0;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        WebSocketSession socketSession = (WebSocketSession) obj;
        Object o = socketSession.getAttribute(USERKEY);
        Object o1 = this.getAttribute(USERKEY);
        if (o == null || o1 == null) {
            return false;
        }
        String key = o.toString();
        String thisKey = o1.toString();
        return key.equals(thisKey);
    }
}
